/*
 * Copyright 2022-2027 中国信息通信研究院云计算与大数据研究所
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package com.config;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
@MapperScan(basePackages = {"com.mapper"}, sqlSessionTemplateRef = "fsqlSessionTemplate")
public class MainConfiguration {

	@Value("${main.datasource.driverClassName}")
    private String driver;
    @Value("${main.datasource.url}")
    private String url;
    @Value("${main.datasource.username}")
    private String username;
    @Value("${main.datasource.password}")
    private String password;
    @Value("${main.datasource.initSize}")
    private int initSize;
    @Value("${main.datasource.minSize}")
    private int minSize;
    @Value("${main.datasource.maxSize}")
    private int maxSize;
    @Value("${main.mapper.path}")
    private String mainMapperPath;
    @Value("${main.mapper.acquireRetryAttempts}")
    private int mainAcquireRetryAttempts;
    @Value("${main.mapper.acquireRetryDelay}")
    private int mainAcquireRetryDelay;
    @Value("${main.mapper.breakAfterAcquireFailure}")
    private boolean breakAfterAcquireFailure;
    @Value("${main.mapper.testConnectionOnCheckin}")
    private boolean testConnectionOnCheckin;
    @Value("${main.mapper.idleConnectionTestPeriod}")
    private int idleConnectionTestPeriod;
    
    @Value("${main.mapper.preferredTestQuery}")
    private String preferredTestQuery;
    @Primary
    @Bean(name = "fdataSource")
    @ConfigurationProperties(prefix = "main.datasource")
    public DataSource fdataSource() throws Exception {
    	ComboPooledDataSource dataSource = new ComboPooledDataSource();
	    dataSource.setDriverClass(driver);
	    dataSource.setJdbcUrl(url);
	    dataSource.setUser(username);
	    dataSource.setPassword(password);
	    dataSource.setAutoCommitOnClose(false);
	    dataSource.setInitialPoolSize(initSize);
	    dataSource.setMinPoolSize(minSize);
	    dataSource.setMaxPoolSize(maxSize);
	    dataSource.setAcquireRetryAttempts(mainAcquireRetryAttempts);
	    dataSource.setAcquireRetryDelay(mainAcquireRetryDelay);
	    dataSource.setBreakAfterAcquireFailure(breakAfterAcquireFailure);
	    dataSource.setTestConnectionOnCheckin(testConnectionOnCheckin);
	    dataSource.setIdleConnectionTestPeriod(idleConnectionTestPeriod);
	    if(preferredTestQuery!=null&&preferredTestQuery.trim().length()>0) {
		    dataSource.setPreferredTestQuery(preferredTestQuery);
	    }
        return dataSource;
    }
    
    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager() throws Exception {
        return new DataSourceTransactionManager(fdataSource());
    }
    
    @Primary
    @Bean
    public SqlSessionFactory fsqlSessionFactory(@Qualifier("fdataSource") DataSource dataSource) {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        try {
            bean.setMapperLocations(resolver.getResources(mainMapperPath));
            return bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    @Primary
    @Bean
    public SqlSessionTemplate fsqlSessionTemplate(@Qualifier("fsqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory);
        return template;
    }
}
